package com.zuo;

import java.util.Arrays;

/*
在Java中，String是一个引用类型，它本身也是一个class。但是，Java编译器对String有特殊处理，即可以直接用"..."来表示一个字符串：

String s1 = "Hello!";
实际上字符串在String内部是通过一个char[]数组表示的，因此，按下面的写法也是可以的：

String s2 = new String(new char[] {'H', 'e', 'l', 'l', 'o', '!'});
Java字符串的一个重要特点就是字符串不可变。这种不可变性是通过内部的private final char[]字段，以及没有任何修改char[]的方法实现的。
* */
public class StringZuo {
    public static void main(String[] args) {
        String s = "Hello";
        System.out.println(s);//Hello

        s = s.toUpperCase();
        System.out.println(s);//HELLO
//        这里看到输出变了，但是其实不是s变量变了，而是s的引用变了，引用了一个全新的字符串

//        1：字符串比较
//        当我们想要比较两个字符串是否相同时，要特别注意，我们实际上是想比较字符串的内容是否相同。必须使用equals()方法而不能用==
        String s1 = "hello";
        String s2 = "hello";

        System.out.println(s1 == s2);//true
        System.out.println(s1.equals(s2));//true
//        从表面上看，两个字符串用==和equals()比较都为true，但实际上那只是Java编译器在编译期，会自动把所有相同的字符串当作一个对象放入常量池，自然s1和s2的引用就是相同的

        String s3 = "hello";
        String s4 = "HELLO".toLowerCase();
        String s5 = "HELLO";
        System.out.println("s3 = " + s3);
        System.out.println("s4 = " + s4);
        System.out.println(s3 == s4);//false
        System.out.println(s3.equals(s4));//true
//      结论：两个字符串比较，必须总是使用equals()方法。

//      比较两个字符串是否相等，忽略大小写，用equalsIgnoreCase（）方法
        System.out.println(s3.equalsIgnoreCase(s5));

//       2: String还提供了很多方法类搜索子串，提取子串：
        System.out.println("是否包含子串 ：" + "Hello".contains("ll"));//true

        System.out.println("hello".indexOf("l"));//
        System.out.println("hello".lastIndexOf("l"));//
        System.out.println("hello".startsWith("he"));//
        System.out.println("hello".endsWith("lo"));//

//        提取子串
        System.out.println("hello".substring(2));//llo
        System.out.println("hello".substring(2,4));//ll

//        3:去除收尾空白字符,空白字符包括空格，\t，\r，\n：
//        trim（）并没有改变字符串的内容，而是返回了一个新的字符串
        System.out.println(" \thello\r\n ".trim());//hello

//        4:String还提供了isEmpty 和isBlank 来判断字符串是否为空和空白字符串：
        System.out.println("".isEmpty()); //true,因为长度为0
        System.out.println("   ".isEmpty());//false,因为长度不是0
        System.out.println("  \n".isBlank());//true,因为只包含空白字符
        System.out.println(" Hello ".isBlank());//false,因为包含非空白字符

//        5:替换子串
//        要在字符串中替换子串，有两种方法。一种是根据字符或字符串替换：
        String s6 = "hello";
        String s7 = s6.replace('l','w');
        System.out.println("s6 = " + s6);
        System.out.println("s7 = " + s7);

//        另一种方法是通过正则表达式替换
        String s8 = "A,,B;C ,D";
        String s9 = s8.replaceAll("[\\,\\;\\s]+",",");
        System.out.println("s9 = " + s9);

//        6:分割字符串
        String s10 = "A,B,C,D";
        String[] s11 = s10.split("\\,");
        System.out.println("s11 = " + s11[0] + s11 [1] + s11[2] + s11 [3]);

//        7:拼接字符串
//        拼接字符串使用静态方法join(),它用指定的字符串连接字符串数组
        String[] arr = {"A", "B", "C"};
        String s12 = String.join("*", arr);
        System.out.println("s12 = " + s12);

//        8:类型转换
//        要把任意基本类型或引用类型转换为字符串，可以使用静态方法valueOf()。这是一个重载方法，编译器会根据参数自动选择合适的方法：
        System.out.println(String.valueOf(123));
        System.out.println(String.valueOf(45.67));
        System.out.println(String.valueOf(true));
        System.out.println(String.valueOf(new Object()));

        //要把字符串转换为其他类型,就需要根据情况
        System.out.println(Integer.parseInt("123"));
        System.out.println(Integer.parseInt("ff",16));//按照16进制转换成int类型

        //把字符串转换成boolean类型:
        System.out.println(Boolean.parseBoolean("true"));
        System.out.println(Boolean.parseBoolean("false"));

        //转换为char
        //string 和char可以相互转换
        char[] cs = "Hello".toCharArray();
        System.out.println("cs = " + cs);

        String s13 = new String(cs);
        System.out.println("s13 = " + s13);

//        练习
        int[] scores = new int[] {88,33,55,22};
        Score sco = new Score(scores);
        sco.printScores();//[88, 33, 55, 22]

        scores[2] = 11;
        sco.printScores();//[88, 33, 11, 22]

    }
}

//设计一个计分数的类
class Score {
    private int[] scores;
//    这里直接使用外部传进来的数组,外部数组改变的时候,实例的属性也会被改变,所以是不安全的
    public Score(int[] scores){
        this.scores = scores;
    }
    public void printScores() {
        System.out.println(Arrays.toString(scores));
    }
}